#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os
import json
import stat
import re

from common.const import RepositoryDataTypeEnum
from common.parse_parafile import ParamFileUtil
from common.cleaner import clear
from ndmp.comm.const import BackupType

from ndmp.comm.log import log
from ndmp.comm.param_base import ParamBase
from ndmp.comm.utils import get_env_in_variable, is_dst_reachable


class BackupParam(ParamBase):
    def __init__(self, req_id):
        super().__init__(req_id)
        self._application: dict = dict()
        self._auth_flag = True
        self.parse_param()

    def parse_param(self):
        try:
            self._param = ParamFileUtil.parse_param_file(self.req_id)
        except Exception as err:
            raise Exception(f"Failed to parse job param file for {err}") from err
        log.info(f"--debug--param,{self._param}")

    def clear(self):
        """
        清理敏感信息
        """
        clear(self.get_src_auth())
        clear(self.get_dst_auth())
        clear(self.get_src_pwd())
        clear(self.get_dst_pwd())

    def get_src_path(self):
        src_path = self._param.get("job", {}).get("protectObject", {}).get("name")
        return src_path

    def get_dst_path(self):
        dst_path = self._param.get("job", {}).get("repositories", [])[1].get("remotePath", "")
        return dst_path

    def get_src_ip(self):
        src_ip = self._param.get("job", {}).get("protectEnv", {}).get("endpoint")
        log.info(f"get_src_ip: {src_ip}")
        return src_ip

    def get_dst_ip(self):
        agent = self._param.get("job", {}).get("extendInfo", {}).get("agents", [])[0]
        dst_ips = agent.get("advanceParams", {}).get("multiIp")
        if dst_ips:
            dst_ips = dst_ips.split(",")
            log.info(f"get_dst_ip: {dst_ips}")
            for dst_ip in dst_ips:
                if is_dst_reachable(self.get_src_ip(), dst_ip, self.get_port()):
                    return dst_ip
        else:
            return agent.get("ip")
        return ""

    def get_port(self):
        s_port = self._param.get("job", {}).get("protectEnv", {}).get("port")
        log.info(f"get_s_port: {s_port}")
        return s_port

    def get_src_auth(self):
        """
        获取本端用户名
        """
        src_auth = get_env_in_variable(f"job_protectEnv_auth_authKey_{self.req_id}")
        return src_auth

    def get_dst_auth(self):
        """
        获取远端端用户名
        """
        dst_auth = get_env_in_variable(f"job_protectEnv_auth_extendInfo_authKey_{self.req_id}")
        return dst_auth

    def get_src_pwd(self):
        """
        获取本端用户密码
        """
        src_pwd = get_env_in_variable(f"job_protectEnv_auth_authPwd_{self.req_id}")
        return src_pwd

    def get_dst_pwd(self):
        """
        获取远端用户密码
        """
        dst_pwd = get_env_in_variable(f"job_protectEnv_auth_extendInfo_authPwd_{self.req_id}")
        return dst_pwd

    def get_copy_format(self):
        data_repository = self.get_repository(RepositoryDataTypeEnum.DATA_REPOSITORY.value)
        return data_repository.get("extendInfo", {}).get("copyFormat", 1)

    def get_repository(self, repository_type):
        repositories = self._param.get("job", {}).get("repositories", [])
        for repository in repositories:
            if repository['repositoryType'] == repository_type:
                return repository
        return {}

    def get_repository_path(self, repository_type):
        repositories_path_list = self.get_repository(repository_type).get("path", [])
        return repositories_path_list[0] if repositories_path_list else ""

    def get_backup_type(self):
        return str(self._param.get("job", {}).get("jobParam", {}).get("backupType", BackupType.FULL_BACKUP.value))

    def get_filter_info(self):
        exclude_filter = self._param.get("job", {}).get("extendInfo", {}).get("filters", '[]')
        filter_info = ''.join(exclude_filter)
        filter_info = re.sub(r'(?<!\\),\s*', ',', filter_info)
        if len(filter_info) > 1 and filter_info.startswith('[') and filter_info.endswith(']'):
            filter_info = filter_info[1:-1]
        log.info(f"exclude_filter,{filter_info}")
        return filter_info

    def get_copy_id(self):
        return self._param.get('job').get('copy')[0].get('id')

    def get_repositories(self):
        return self._param.get('job').get('repositories')

    def get_meta_info(self):
        meta_path = self.get_repository_path(RepositoryDataTypeEnum.META_REPOSITORY.value)
        file_name = "ndmp_backup_info"
        meta_info_file = os.path.join(meta_path, file_name)
        if not os.path.exists(meta_info_file):
            flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
            modes = stat.S_IWUSR | stat.S_IRUSR
            default_param = {
                "fullBackup": {"copyId": ""}, "incrementBackup": [],
                "diffBackup": {"copyId": "", "copyLevel": ""}, "latestType": ""
            }
            with os.fdopen(os.open(meta_info_file, flags, modes), 'w') as m_file:
                m_file.write(json.dumps(default_param))
            return default_param
        with open(meta_info_file, "r", encoding='UTF-8') as file:
            old_backup_info = file.read().strip()
            param = json.loads(old_backup_info)
        log.info(f"ndmp_backup_info,{param}")
        return param

    def get_file_path(self):
        path = self._param.get("job", {}).get("protectObject", {}).get("extendInfo", {}).get("path", "").strip()
        return path.split(",") if path else []

    def get_backup_level(self):
        meta_path = self.get_repository_path(RepositoryDataTypeEnum.META_REPOSITORY.value)
        file_name = "ndmp_backup_info"
        meta_info_file = os.path.join(meta_path, file_name)
        if os.path.exists(meta_info_file):
            with open(meta_info_file, "r", encoding='UTF-8') as file:
                backup_info = file.read().strip()
                param = json.loads(backup_info)
                level = param["diffBackup"]["copyLevel"]
                if not level:
                    level = "2"
                return level
        return ""

    def get_sub_job_info(self):
        job_info_str = self._param.get("subJob", {}).get("jobInfo", '')
        job_info = json.loads(job_info_str) if job_info_str else {}
        return job_info

    def get_sub_job_name(self):
        sub_job_name = self._param.get("subJob", {}).get("jobName", "")
        return sub_job_name